---
category: Level 3 — Advanced
created: '2020-03-03'
keywords:
title: Make a draggable element
updated: '2021-05-07'
---

Assume that we want to turn the following element to draggable element:

```html
<div id="dragMe" class="draggable">Drag me</div>
```

The element needs to have the following styles:

```css
.draggable {
    /* Indicate the element draggable */
    cursor: move;

    /* It will be positioned absolutely */
    position: absolute;

    /* Doesn't allow to select the content inside */
    user-select: none;
}
```

In order to make it draggable, we need to handle three events:

-   `mousedown` on the element: Track the current position of mouse
-   `mousemove` on `document`: Calculate how far the mouse has been moved, and determine the position of element
-   `mouseup` on `document`: Remove the event handlers of `document`

```js
// The current position of mouse
let x = 0;
let y = 0;

// Query the element
const ele = document.getElementById('dragMe');

// Handle the mousedown event
// that's triggered when user drags the element
const mouseDownHandler = function (e) {
    // Get the current mouse position
    x = e.clientX;
    y = e.clientY;

    // Attach the listeners to `document`
    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', mouseUpHandler);
};

const mouseMoveHandler = function (e) {
    // How far the mouse has been moved
    const dx = e.clientX - x;
    const dy = e.clientY - y;

    // Set the position of element
    ele.style.top = `${ele.offsetTop + dy}px`;
    ele.style.left = `${ele.offsetLeft + dx}px`;

    // Reassign the position of mouse
    x = e.clientX;
    y = e.clientY;
};

const mouseUpHandler = function () {
    // Remove the handlers of `mousemove` and `mouseup`
    document.removeEventListener('mousemove', mouseMoveHandler);
    document.removeEventListener('mouseup', mouseUpHandler);
};

ele.addEventListener('mousedown', mouseDownHandler);
```

> **Tip**
>
> This post uses the [Attach event handlers inside other handlers](https://phuoc.ng/collection/html-dom/attach-event-handlers-inside-other-handlers/) tip

## Use cases

We can use the technique in this post to

1. [Create a range slider](https://phuoc.ng/collection/html-dom/create-a-range-slider/)
2. [Create an image comparison slider](https://phuoc.ng/collection/html-dom/create-an-image-comparison-slider/)
3. [Create resizable split views](https://phuoc.ng/collection/html-dom/create-resizable-split-views/)
4. [Drag to scroll](https://phuoc.ng/collection/html-dom/drag-to-scroll/)
5. [Resize columns of a table](https://phuoc.ng/collection/html-dom/resize-columns-of-a-table/)

## Demo

<Playground>
```html
<div class="container">
    <div class="draggable" id="dragMe">Drag me</div>
</div>
```

```css
.container {
    /* Center the content */
    align-items: center;
    display: flex;
    justify-content: center;

    /* Misc */
    min-height: 32rem;
}
.draggable {
    /* Required styles */
    cursor: move;
    position: absolute;
    user-select: none;

    /* Center the content */
    align-items: center;
    display: flex;
    justify-content: center;

    /* Misc */
    border: 1px solid #cbd5e0;
    height: 8rem;
    width: 8rem;
}
```

```js
document.addEventListener('DOMContentLoaded', function () {
    // The current position of mouse
    let x = 0;
    let y = 0;

    // Query the element
    const ele = document.getElementById('dragMe');

    // Handle the mousedown event
    // that's triggered when user drags the element
    const mouseDownHandler = function (e) {
        // Get the current mouse position
        x = e.clientX;
        y = e.clientY;

        // Attach the listeners to document
        document.addEventListener('mousemove', mouseMoveHandler);
        document.addEventListener('mouseup', mouseUpHandler);
    };

    const mouseMoveHandler = function (e) {
        // How far the mouse has been moved
        const dx = e.clientX - x;
        const dy = e.clientY - y;

        // Set the position of element
        ele.style.top = (ele.offsetTop + dy) + 'px';
        ele.style.left = (ele.offsetLeft + dx) + 'px';

        // Reassign the position of mouse
        x = e.clientX;
        y = e.clientY;
    };

    const mouseUpHandler = function () {
        // Remove the handlers of mousemove and mouseup
        document.removeEventListener('mousemove', mouseMoveHandler);
        document.removeEventListener('mouseup', mouseUpHandler);
    };

    ele.addEventListener('mousedown', mouseDownHandler);
});
```
</Playground>

## See also

-   [Attach event handlers inside other handlers](https://phuoc.ng/collection/html-dom/attach-event-handlers-inside-other-handlers/)
-   [Attach or detach an event handler](https://phuoc.ng/collection/html-dom/attach-or-detach-an-event-handler/)
-   [Calculate the mouse position relative to an element](https://phuoc.ng/collection/html-dom/calculate-the-mouse-position-relative-to-an-element/)
-   [Create a range slider](https://phuoc.ng/collection/html-dom/create-a-range-slider/)
-   [Create an image comparison slider](https://phuoc.ng/collection/html-dom/create-an-image-comparison-slider/)
-   [Create resizable split views](https://phuoc.ng/collection/html-dom/create-resizable-split-views/)
-   [Drag and drop element in a list](https://phuoc.ng/collection/html-dom/drag-and-drop-element-in-a-list/)
-   [Drag and drop table column](https://phuoc.ng/collection/html-dom/drag-and-drop-table-column/)
-   [Drag and drop table row](https://phuoc.ng/collection/html-dom/drag-and-drop-table-row/)
-   [Drag to scroll](https://phuoc.ng/collection/html-dom/drag-to-scroll/)
-   [Make a resizable element](https://phuoc.ng/collection/html-dom/make-a-resizable-element/)
-   [Resize columns of a table](https://phuoc.ng/collection/html-dom/resize-columns-of-a-table/)
-   [Set css style for an element](https://phuoc.ng/collection/html-dom/set-css-style-for-an-element/)
-   [Show a ghost element when dragging an element](https://phuoc.ng/collection/html-dom/show-a-ghost-element-when-dragging-an-element/)
-   [Zoom an image](https://phuoc.ng/collection/html-dom/zoom-an-image/)
